#include "parabolathrow.h"

#include <cassert>
#define _USE_MATH_DEFINES
#include <cmath>

const float ParabolaThrow::gravity = 9.81f;
const float ParabolaThrow::invalid_ball = -10.0f;
const float ParabolaThrow::default_step = 0.25f;

ParabolaThrow::ParabolaThrow() :
    ball_(invalid_ball, invalid_ball, 9.5f),
    speed_(1.0f),
    angle_(0.0f),
    step_(default_step),
    start_x_(0.0f),
    start_y_(0.0f)
{
}

bool ParabolaThrow::active_ball() const
{
    return ball_.getX() != invalid_ball && ball_.getY() != invalid_ball;
}

const Ball &ParabolaThrow::ball() const
{
    return ball_;
}

void ParabolaThrow::throwBall(float x, float y, float speed, float angle)
{
    if(active_ball()) return;

    ball_.setX(x);
    ball_.setY(y);
    start_x_ = x;
    start_y_ = y;
    speed_ = speed;
    angle_ = angle;
    assert(active_ball());
}

void ParabolaThrow::move()
{
    static const float defaultSpeed = 1.0f;

    if(!active_ball()) return;

    float newX =  (defaultSpeed + speed_) * step_ * cosf(angle_ * M_PI / 180);
    float newY =  ((defaultSpeed + speed_) * step_ * sinf(angle_ * M_PI / 180)) - (0.5 * gravity * step_ * step_);

    ball_.setX(start_x_ + newX);
    ball_.setY(start_y_ + newY);

    step_ += default_step;
    assert(active_ball());
}

void ParabolaThrow::reset()
{
    ball_.setX(invalid_ball);
    ball_.setY(invalid_ball);
    step_ = default_step;
    speed_ = 1.0f;
    angle_ = 0.0f;
    assert(!active_ball());
}
